﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Numerics;

namespace CNFProblem.CNF
{
    public class Variables : IEnumerable<Variable>
    {
        private List<Variable> _variables = new List<Variable>();

        public int Count { get { return _variables.Count; } }

        private int _lastId = 0;

        public int Add(string name)
        {
            var used = _variables.FirstOrDefault(x => x.Name == name);
            if (used != null)
                return used.Id;

            var vr = new Variable()
            {
                Id = ++_lastId,
                Name = name
            };

            _variables.Add(vr);

            return vr.Id;
        }

        /// <summary>
        /// Tworzy slownik ze wszystkimi id zmiennych ustawionymi na false
        /// </summary>
        /// <returns>Slownik zmiennych</returns>
        public Dictionary<int, bool> GetAsFalse()
        {
            Dictionary<int, bool> d = new Dictionary<int, bool>();
            for (int i = 0; i < Count; i++)
            {
                d.Add(_variables[i].Id, false);
            }

            return d;
        }

        /// <summary>
        /// Permutuje wartosci wedlug id
        /// </summary>
        /// <param name="id">ID</param>
        /// <param name="vals">Wartosci</param>
        public void Permute(BigInteger id, Dictionary<int, bool> vals)
        {
            var ba = id.ToByteArray();
            var keys = vals.Keys.ToList();

            for (int i = 0; i < vals.Count; i++)
            {
                int j = i / 8;
                int k = 0;
                if (j < ba.Length)
                {
                    k = (ba[j] >> (i % 8)) & 1;
                }
                bool b = k == 1;

                vals[keys[i]] = b;
            }
        }

        public string GetName(int i)
        {
            return _variables.Where(x => x.Id == i).Select(x => x.Name).First();
        }

        public Dictionary<int, Variable> IdToVariable()
        {
            return _variables.ToDictionary(x => x.Id);
        }

        public void Clear()
        {
            _variables.Clear();
            _lastId = 0;
        }

        public IEnumerator<Variable> GetEnumerator()
        {
            return _variables.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _variables.GetEnumerator();
        }
    }
}
